import numpy as np
import cv2
import matplotlib.pyplot as plt
from skimage.metrics import structural_similarity
from conv_net import ConvNet
import time

network = ConvNet()
network.load_params("1.pkl")
# test_array=np.ones([1,3,60,60])
# start_time=time.process_time()
# for i in range(500):
#     network.predict(test_array)
# print(time.process_time()-start_time)

image_array = np.zeros([9, 9, 60, 60, 3]).astype("uint8")

def divide_ij(img_focus,L):#没办法还是用来自己写的for循环
    image_array = np.zeros([9,9,L,L,3]).astype("uint8")
    for i in range(9):
        for j in range(9):
            image_array[i][j]=img_focus[0+i*L:0+(i+1)*L,j*L:(j+1)*L]
    return image_array


def aHash(img):
    # 均值哈希算法
    # 缩放为8*8
    img = cv2.resize(img, (8, 8))
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # s为像素和初值为0，hash_str为hash值初值为''
    s = 0
    hash_str = ''
    # 遍历累加求像素和
    for i in range(8):
        for j in range(8):
            s = s + gray[i, j]
    # 求平均灰度
    avg = s / 64
    # 灰度大于平均值为1相反为0生成图片的hash值
    for i in range(8):
        for j in range(8):
            if gray[i, j] > avg:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'
    return hash_str


def dHash(img):
    # 差值哈希算法
    # 缩放8*8
    img = cv2.resize(img, (8, 8))
    # 转换灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    hash_str = ''
    # 每行前一个像素大于后一个像素为1，相反为0，生成哈希
    for i in range(8):
        for j in range(8):
            if gray[i, j] > gray[i, j + 1]:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'
    return hash_str


def pHash(img):
    # 感知哈希算法
    # 缩放32*32
    img = cv2.resize(img, (32, 32))  # , interpolation=cv2.INTER_CUBIC

    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 将灰度图转为浮点型，再进行dct变换
    dct = cv2.dct(np.float32(gray))
    # opencv实现的掩码操作
    dct_roi = dct[0:8, 0:8]

    hash = []
    avreage = np.mean(dct_roi)
    for i in range(dct_roi.shape[0]):
        for j in range(dct_roi.shape[1]):
            if dct_roi[i, j] > avreage:
                hash.append(1)
            else:
                hash.append(0)
    return hash


def calculate(image1, image2):
    # 灰度直方图算法
    # 计算单通道的直方图的相似值
    hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])
    hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])
    # 计算直方图的重合度
    degree = 0
    for i in range(len(hist1)):
        if hist1[i] != hist2[i]:
            degree = degree + \
                     (1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))
        else:
            degree = degree + 1
    degree = degree / len(hist1)
    return degree


def classify_hist_with_split(image1, image2, size=(256, 256)):
    # RGB每个通道的直方图相似度
    # 将图像resize后，分离为RGB三个通道，再计算每个通道的相似值
    image1 = cv2.resize(image1, size)
    image2 = cv2.resize(image2, size)
    sub_image1 = cv2.split(image1)
    sub_image2 = cv2.split(image2)
    sub_data = 0
    for im1, im2 in zip(sub_image1, sub_image2):
        sub_data += calculate(im1, im2)
    sub_data = sub_data / 3
    return sub_data


def cmpHash(hash1, hash2):
    # Hash值对比
    # 算法中1和0顺序组合起来的即是图片的指纹hash。顺序不固定，但是比较的时候必须是相同的顺序。
    # 对比两幅图的指纹，计算汉明距离，即两个64位的hash值有多少是不一样的，不同的位数越小，图片越相似
    # 汉明距离：一组二进制数据变成另一组数据所需要的步骤，可以衡量两图的差异，汉明距离越小，则相似度越高。汉明距离为0，即两张图片完全一样
    n = 0
    # hash长度不同则返回-1代表传参出错
    if len(hash1) != len(hash2):
        return -1
    # 遍历判断
    for i in range(len(hash1)):
        # 不相等则n计数+1，n最终为相似度
        if hash1[i] != hash2[i]:
            n = n + 1
    return n
def judge_is_similiar0(img1,img2):
    str1 = pHash(img1)
    str2 = pHash(img2)
    Hash_num = cmpHash(str1, str2)
    print('h:'+str(Hash_num))
    if Hash_num>8:
        return 0
    else:
        return 1



def judge_is_similiar1(img1,img2):
    img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    ssim_num=structural_similarity(img1_gray,img2_gray)
    str1 = pHash(img1)
    str2 = pHash(img2)
    n=cmpHash(str1,str2)
    if ssim_num<0.3:
        return 0
    else:
        return 1



def pic2data(img):#输入框选后的彩色图片，uint8型
    img=cv2.resize(img,(60*9,60*9))
    #plt.imshow(img)
    L=img.shape[0]//9
    image_array=divide_ij(img,L)
    classify_map=np.ones([9,9])*-1
    img_moudle=np.zeros([15,L,L,3]).astype('uint8')
    moudle_num=1
    img_moudle[0]=image_array[0][0]
    classify_map[0][0]=0
    for i in range(9):
        for j in range(9):
            flag=0
            for k in range(moudle_num):
                if judge_is_similiar1(image_array[i][j],img_moudle[k])==1:
                    classify_map[i][j]=k
                    flag=1
                    break
            if flag==0:
                img_moudle[moudle_num]=image_array[i][j]
                classify_map[i][j] = moudle_num
                moudle_num=moudle_num+1
    return classify_map

def pic2data_with_cnn(img):
    img = cv2.resize(img, (60 * 9, 60 * 9))
    # plt.imshow(img)
    L = 60
    image_array = divide_ij(img, L)
    image_array1 = image_array.reshape(9 * 9, 60,
                                       60, 3)
    image_array1 = image_array1.transpose(0, 3, 1, 2) / 255

    result = network.predict(image_array1, train_flg=False)
    classify_map = np.argmax(result, axis=1) + 1
    classify_map = classify_map.reshape(9, 9)
    return classify_map

def calculate_cor(classify_map):#返回(a,b,c,d)  第a行第b列 与第c行第d列交换
    classify_map_fliped = cv2.flip(classify_map, 1)

    def indexij(i, j):  # 定义函数，方便判断是否出界
        if (i < 0) or (i > 8) or (j < 0) or (j > 8):
            return -1
        else:
            return classify_map[i, j]

    def indexij2(i, j):
        if (i < 0) or (i > 8) or (j < 0) or (j > 8):
            return -1
        else:
            return classify_map_fliped[i, j]

    swapij = [[-1, -1], [-1, -1]]  # 用于记录交换位置
    stopflag = 0
    for i in range(9).__reversed__():
        if stopflag == 1:
            break
        for j in range(9):
            if classify_map[i][j] == 20:  # 20代表非可交换元素
                continue
            else:
                a = indexij(i, j)
                if (indexij(i, j + 1) == a) and (indexij(i, j + 2) != 20):
                    if indexij(i - 1, j + 2) == a:
                        swapij = [[i - 1, j + 2], [i, j + 2]]
                    elif indexij(i, j + 3) == a:
                        swapij = [[i, j + 3], [i, j + 2]]
                    elif indexij(i + 1, j + 2) == a:
                        swapij = [[i + 1, j + 2], [i, j + 2]]
                elif indexij(i, j + 1) != 20:
                    if (indexij(i - 1, j + 1) == a) and (indexij(i, j + 2) == a):
                        swapij = [[i - 1, j + 1], [i, j + 1]]
                    elif (indexij(i - 1, j + 1) == a) and (indexij(i + 1, j + 1) == a):
                        swapij = [[i, j], [i, j + 1]]
                    elif (indexij(i, j + 2) == a) and (indexij(i + 1, j + 1) == a):
                        swapij = [[i, j + 1], [i + 1, j + 1]]
                    elif (indexij(i - 1, j + 1) == a) and (indexij(i - 2, j + 1) == a):
                        swapij = [[i, j], [i, j + 1]]
                    elif (indexij(i, j + 2) == a) and (indexij(i, j + 3) == a):
                        swapij = [[i, j], [i, j + 1]]
                    elif (indexij(i + 1, j + 1) == a) and (indexij(i + 2, j + 1) == a):
                        swapij = [[i, j], [i, j + 1]]

                if (indexij(i + 1, j) == a) and (indexij(i + 3, j) == a):
                    swapij = [[i+2, j], [i+3, j]]
                elif (indexij(i + 1, j) == a) and (indexij(i -2, j) == a):
                    swapij = [[i-1, j], [i-2, j]]

            if swapij[0][0] == -1:
                continue
            else:
                stopflag = 1
                break

    if stopflag == 0:
        for i in range(9).__reversed__():
            if stopflag == 1:
                break
            for j in range(9):
                if classify_map_fliped[i][j] == 20:
                    continue
                else:
                    a = indexij2(i, j)
                    if indexij2(i, j + 1) == a:
                        if indexij2(i - 1, j + 2) == a:
                            swapij = [[i - 1, j + 2], [i, j + 2]]
                        elif indexij2(i, j + 3) == a:
                            swapij = [[i, j + 3], [i, j + 2]]
                        elif indexij2(i + 1, j + 2) == a:
                            swapij = [[i + 1, j + 2], [i, j + 2]]
                    elif indexij2(i, j + 1) != 20:
                        if (indexij2(i - 1, j + 1) == a) and (indexij2(i, j + 2) == a):
                            swapij = [[i - 1, j + 1], [i, j + 1]]
                        elif (indexij2(i - 1, j + 1) == a) and (indexij2(i + 1, j + 1) == a):
                            swapij = [[i, j], [i, j + 1]]
                        elif (indexij2(i, j + 2) == a) and (indexij2(i + 1, j + 1) == a):
                            swapij = [[i, j + 1], [i + 1, j + 1]]
                        elif (indexij2(i - 1, j + 1) == a) and (indexij2(i - 2, j + 1) == a):
                            swapij = [[i, j], [i, j + 1]]
                        elif (indexij2(i, j + 2) == a) and (indexij2(i, j + 3) == a):
                            swapij = [[i, j], [i, j + 1]]
                        elif (indexij2(i + 1, j + 1) == a) and (indexij2(i + 2, j + 1) == a):
                            swapij = [[i, j], [i, j + 1]]
                    if swapij[0][0] == -1:
                        continue
                    else:
                        stopflag = 1
                        swapij[0][0] = swapij[0][0]
                        swapij[0][1] = 8 - swapij[0][1]
                        swapij[1][0] = swapij[1][0]
                        swapij[1][1] = 8 - swapij[1][1]
                        break
    return (swapij[0][0] + 1, swapij[0][1] + 1, swapij[1][0] + 1, swapij[1][1] + 1)